package cn.sfrog.project.biz.admin.pay.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.sfrog.project.biz.admin.pay.PayFactory;
import cn.sfrog.project.biz.admin.service.IBizUserRechargePaymentService;
import cn.sfrog.project.biz.admin.task.AsyncExecutor;
import cn.sfrog.project.biz.admin.task.OrderStatusQueryTask;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Component
@Qualifier("aliPayService")
@Slf4j
public class AliPayService extends PayFactory {
    @Autowired
    private IBizUserRechargePaymentService paymentService;

    @Autowired
    private AsyncExecutor asyncExecutor;

    @Value("${pay.alipay.appid}")
    private String appid;

    @Value("${pay.alipay.privateKey}")
    private String privateKey;

    @Value("${pay.alipay.publicKey}")
    private String publicKey;

    @Value("${pay.alipay.signType}")
    private String signType;

    @Value("${pay.alipay.notifyUrl}")
    private String notifyUrl;

    @Value("${pay.alipay.gatewayUrl}")
    private String gatewayUrl;

    @Value("${pay.alipay.orderExpireTime}")
    private Integer orderExpireTime;

    @Override
    public String buildPayParams(String tradeSn, BigDecimal price) {
        try {
            AlipayConfig alipayConfig = new AlipayConfig();
            alipayConfig.setServerUrl(gatewayUrl);
            alipayConfig.setAppId(appid);
            alipayConfig.setPrivateKey(privateKey);
            alipayConfig.setFormat("json");
            alipayConfig.setAlipayPublicKey(publicKey);
            alipayConfig.setCharset("UTF8");
            alipayConfig.setSignType(signType);
            AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            request.setNotifyUrl(notifyUrl);
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            DateTime dateTime = DateUtil.offsetMinute(new Date(), orderExpireTime);
            model.setTimeExpire(DateUtil.format(dateTime, "yyyy-MM-dd HH:mm:ss"));
            model.setProductCode("QUICK_MSECURITY_PAY");
            model.setOutTradeNo(tradeSn);
            model.setTotalAmount(price.toString());
            model.setSubject("支付");
            request.setBizModel(model);
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            if (!response.isSuccess()) {
                return response.getMsg();
            }
            asyncExecutor.executeAsync(new OrderStatusQueryTask(orderExpireTime,tradeSn,this));
            return response.getBody();
        } catch (Exception e) {
            return "请求支付失败";
        }
    }

    @Override
    public Map<String, Object> callback(HttpServletRequest request, HttpServletResponse response) {

        //获取支付宝POST过来反馈信息
        Map< String , Object > result = new HashMap< String , Object >();
        Map< String , String > params = new HashMap < String , String > ();
        try{
            request.setCharacterEncoding("UTF-8");
            Map requestParams = request.getParameterMap();
            for(Iterator iter = requestParams.keySet().iterator(); iter.hasNext();){
                String name = (String)iter.next();
                String[] values = (String [])requestParams.get(name);
                String valueStr = "";
                for(int i = 0;i < values.length;i ++ ){
                    valueStr =  (i==values.length-1)?valueStr + values [i]:valueStr + values[i] + ",";
                }
                //乱码解决，这段代码在出现乱码时使用。
//                valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                params.put (name,valueStr);
            }
            //切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
            //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
            boolean flag = AlipaySignature.rsaCheckV1 (params,publicKey, "UTF8",signType);
            if(flag){
                String tradeNo = params.get("out_trade_no");
                String aliTradeNo = params.get("trade_no");
                String payTimeStr = params.get("gmt_payment");
                paymentService.paySuccess(tradeNo,aliTradeNo,new Date());
                result.put("res", "success");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        result.put("res", "error");
        return result;
    }

    @Override
    public boolean queryPayStatus(String sn) throws Exception{
        //查询支付状态
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl(gatewayUrl);
        alipayConfig.setAppId(appid);
        alipayConfig.setPrivateKey(privateKey);
        alipayConfig.setFormat("json");
        alipayConfig.setAlipayPublicKey(publicKey);
        alipayConfig.setCharset("UTF8");
        alipayConfig.setSignType("RSA2");
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        model.setOutTradeNo(sn);
        request.setBizModel(model);
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            if("TRADE_SUCCESS".equals(response.getTradeStatus())){
                //支付成功
                paymentService.paySuccess(response.getOutTradeNo(),response.getTradeNo(),response.getSendPayDate());
                return true;
            }
        }
        return false;
    }

    @Override
    public void closeOrder(String sn) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl,appid,privateKey,"json","UTF8",publicKey,signType);
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("trade_no", sn);
        request.setBizContent(bizContent.toString());
        AlipayTradeCloseResponse response = alipayClient.execute(request);
        if(!response.isSuccess()){
            log.error("关闭订单失败，流水编号："+sn + " " + response.getMsg());
        }
    }
}
